/*!
 * \file decimal.h
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief 十进制浮点数比较工具，主要用于浮点数据的精确比较
 * 
 * \details 提供高精度浮点数比较和运算功能，包括：
 *          - 浮点数精确相等比较
 *          - 大于、小于、大于等于、小于等于比较
 *          - 浮点数四舍五入
 *          - 浮点数取模运算
 *          
 *          在金融计算中，由于浮点数的精度限制，
 *          直接使用==、>、<等操作符可能产生不准确的结果。
 *          此工具库通过引入误差容限(EPSILON)来解决这个问题。
 *          
 *          特别适用于：
 *          - 价格、数量等金融数据比较
 *          - 交易算法中的数值判断
 *          - 高精度计算结果验证
 */
#pragma once
#include <math.h>

/*!
 * \brief 十进制浮点数比较工具命名空间
 * 
 * \details 包含一系列用于高精度浮点数比较和运算的内联函数，
 *          通过误差容限机制解决浮点数精度问题。
 */
namespace decimal
{
	/// 浮点数比较的误差容限（1e-6）
	const double EPSINON = 1e-6;

	/*!
	 * \brief 浮点数四舍五入
	 * \param v 待四舍五入的数值
	 * \param exp 精度倍数，默认为1
	 * \return 四舍五入后的结果
	 * 
	 * \details 通过乘以精度倍数、四舍五入、再除以精度倍数的方式
	 *          实现指定精度的四舍五入。
	 * 
	 * \example
	 * \code
	 * double result = rnd(3.14159, 100);  // 结果为3.14
	 * double result = rnd(3.14159, 1000); // 结果为3.142
	 * \endcode
	 */
	inline double rnd(double v, int exp = 1)
	{
		return round(v*exp) / exp;
	}

	/*!
	 * \brief 判断两个浮点数是否相等
	 * \param a 第一个数值
	 * \param b 第二个数值，默认为0.0
	 * \return 相等返回true，否则返回false
	 * 
	 * \details 通过检查两数差的绝对值是否小于误差容限来判断相等性。
	 *          避免了直接使用==运算符可能产生的精度问题。
	 * 
	 * \example
	 * \code
	 * bool isEqual = eq(0.1 + 0.2, 0.3);  // 返回true，避免浮点精度问题
	 * \endcode
	 */
	inline bool eq(double a, double b = 0.0)
	{
		return(fabs(a - b) < EPSINON);
	}

	/*!
	 * \brief 判断第一个数是否大于第二个数
	 * \param a 第一个数值
	 * \param b 第二个数值，默认为0.0
	 * \return a > b 返回true，否则返回false
	 * 
	 * \details 通过检查差值是否大于误差容限来判断大小关系，
	 *          确保比较的准确性。
	 */
	inline bool gt(double a, double b = 0.0)
	{
		return a - b > EPSINON;
	}

	/*!
	 * \brief 判断第一个数是否小于第二个数
	 * \param a 第一个数值
	 * \param b 第二个数值，默认为0.0
	 * \return a < b 返回true，否则返回false
	 * 
	 * \details 通过检查反向差值是否大于误差容限来判断大小关系。
	 */
	inline bool lt(double a, double b = 0.0)
	{
		return b - a > EPSINON;
	}

	/*!
	 * \brief 判断第一个数是否大于等于第二个数
	 * \param a 第一个数值
	 * \param b 第二个数值，默认为0.0
	 * \return a >= b 返回true，否则返回false
	 * 
	 * \details 组合使用gt()和eq()函数来实现大于等于的判断。
	 */
	inline bool ge(double a, double b = 0.0)
	{
		return gt(a, b) || eq(a, b);
	}

	/*!
	 * \brief 判断第一个数是否小于等于第二个数
	 * \param a 第一个数值
	 * \param b 第二个数值，默认为0.0
	 * \return a <= b 返回true，否则返回false
	 * 
	 * \details 组合使用lt()和eq()函数来实现小于等于的判断。
	 */
	inline bool le(double a, double b = 0.0)
	{
		return lt(a, b) || eq(a, b);
	}

	/*!
	 * \brief 计算浮点数取模运算
	 * \param a 被除数
	 * \param b 除数
	 * \return a对b的模运算结果
	 * 
	 * \details 实现浮点数的取模运算：mod(a,b) = a/b - round(a/b)
	 *          返回值范围在[-0.5, 0.5]之间。
	 * 
	 * \example
	 * \code
	 * double result = mod(5.7, 2.0);  // 结果约为-0.15 (5.7/2.0=2.85, round(2.85)=3, 2.85-3=-0.15)
	 * \endcode
	 */
	inline double mod(double a, double b)
	{
		return a / b - round(a / b);
	}
	
};